<!--
 * Tencent is pleased to support the open source community by making BK-JOB蓝鲸智云作业平台 available.
 *
 * Copyright (C) 2021 THL A29 Limited, a Tencent company.  All rights reserved.
 *
 * BK-JOB蓝鲸智云作业平台 is licensed under the MIT License.
 *
 * License for BK-JOB蓝鲸智云作业平台:
 *
 *
 * Terms of the MIT License:
 * ---------------------------------------------------
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
 * documentation files (the "Software"), to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
 * to permit persons to whom the Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or substantial portions of
 * the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
 * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
-->

<template>
    <div class="file-source-create-form" v-bkloading="{ isLoading }">
        <jb-form
            v-if="!isLoading"
            ref="fileSourceform"
            form-type="vertical"
            :model="formData"
            :rules="rules">
            <jb-form-item
                :label="$t('file.文件源标识.label')"
                required
                property="code">
                <bk-input
                    v-model="formData.code"
                    :placeholder="$t('file.请输入文件源标识')" />
            </jb-form-item>
            <jb-form-item
                :label="$t('file.文件源别名.label')"
                required
                property="alias">
                <jb-input
                    v-model="formData.alias"
                    :maxlength="32"
                    :placeholder="$t('file.为文件源起一个可读性较好的别名')" />
            </jb-form-item>
            <jb-form-item
                required
                :label="$t('file.类型.label')">
                <bk-radio-group v-model="formData.storageType">
                    <bk-radio-button value="OSS">{{ $t('file.对象存储') }}</bk-radio-button>
                </bk-radio-group>
            </jb-form-item>
            <jb-form-item
                required
                :label="$t('file.来源')">
                <bk-radio-group
                    v-model="formData.fileSourceTypeCode"
                    @change="handleFileSourceChange">
                    <bk-radio-button
                        v-for="item in sourceTypeList"
                        :key="item.code"
                        :value="item.code">
                        <img :src="item.icon" style="width: 1em; height: 1em; vertical-align: middle;">
                        <span style="vertical-align: middle;">{{ item.name }}</span>
                    </bk-radio-button>
                </bk-radio-group>
            </jb-form-item>
            <render-file-source-param
                :file-source-type-code="formData.fileSourceTypeCode"
                :param-map="formData.fileSourceInfoMap"
                @on-change="handleFileSourceParamsChange" />
            <jb-form-item
                required
                :label="$t('file.公共存储')">
                <bk-checkbox v-model="formData.publicFlag">
                    {{ $t('file.设为公共存储') }}
                </bk-checkbox>
            </jb-form-item>
            <jb-form-item
                v-if="formData.publicFlag"
                :label="$t('file.共享对象')"
                required
                property="sharedAppIdList">
                <div class="share-object-box">
                    <bk-select
                        class="share-app-select"
                        :clearable="false"
                        searchable
                        multiple
                        :disabled="formData.shareToAllApp"
                        v-model="formData.sharedAppIdList">
                        <bk-option
                            v-for="option in appList"
                            :key="option.id"
                            :id="option.id"
                            :name="option.name" />
                    </bk-select>
                    <bk-checkbox v-model="formData.shareToAllApp">{{ $t('file.全业务') }}</bk-checkbox>
                </div>
            </jb-form-item>
            <jb-form-item
                required
                :label="$t('file.身份凭证')"
                property="credentialId">
                <bk-select v-model="formData.credentialId" :clearable="false">
                    <auth-option
                        v-for="option in fileFourceTicketList"
                        :key="option.id"
                        auth="ticket/use"
                        :permission="option.canUse"
                        :resource-id="option.id"
                        :id="option.id"
                        :name="option.name" />
                </bk-select>
            </jb-form-item>
            <jb-form-item :label="$t('file.文件前缀名')">
                <bk-select
                    v-model="filePrefixType"
                    :clearable="false">
                    <bk-option id="${UUID}" name="UUID" />
                    <bk-option id="custom" :name="$t('file.自定义字符串')" />
                </bk-select>
                <bk-input
                    v-if="isCustomFilePrefix"
                    v-model="formData.filePrefix"
                    style="margin-top: 10px;" />
            </jb-form-item>
            <jb-form-item
                required
                :label="$t('file.接入点')">
                <div class="access-point-box">
                    <bk-select
                        v-model="formData.workerSelectScope"
                        :clearable="false"
                        class="worker-select">
                        <bk-option
                            v-for="option in workerSelectModeList"
                            :key="option.id"
                            :id="option.id"
                            :name="option.name" />
                    </bk-select>
                    <bk-checkbox v-model="isWorkerSelectScopeAuto" :disabled="workersList.length < 1">
                        {{ $t('file.自动选择接入点') }}
                    </bk-checkbox>
                </div>
                <div v-if="!isWorkerSelectScopeAuto && workersList.length > 0">
                    <bk-radio-group
                        v-model="formData.workerId"
                        class="worker-box">
                        <bk-radio-button
                            v-for="option in workersList"
                            :key="option.id"
                            :value="option.id">
                            <div class="worker-item">
                                <span>{{ option.innerIp }} </span>
                                <span v-html="option.latencyHtml" />
                            </div>
                        </bk-radio-button>
                    </bk-radio-group>
                </div>
            </jb-form-item>
        </jb-form>
    </div>
</template>
<script>
    import I18n from '@/i18n';
    import FileSourceModel from '@model/file/file-source';
    import FileManageService from '@service/file-source-manage';
    import FileSourceType from '@service/file-source-type';
    import TicketService from '@service/ticket-manage';
    import FileWorker from '@service/file-worker';
    import AppService from '@service/app-manage';
    import {
        fileSourceAliasNameRule,
    } from '@utils/validator';
    import RenderFileSourceParam from './components/render-file-source-param';

    const getDefaultData = () => ({
        // ID,更新文件源的时候需要传入，新建文件源不需要
        id: -1,
        // 文件源名称
        alias: '',
        // 文件源Code
        code: '',
        // 文件源凭证Id
        credentialId: '',
        // 文件前缀：后台自动生成UUID传${UUID}，自定义字符串直接传
        filePrefix: FileSourceModel.FILE_PERFIX_UUID,
        // 文件源参数
        fileSourceInfoMap: {},
        // 文件源类型Code
        fileSourceTypeCode: '',
        // 是否为公共文件源
        publicFlag: true,
        // 是否共享到全业务
        shareToAllApp: false,
        // 共享的业务Id列表
        sharedAppIdList: [],
        // 存储类型
        storageType: 'OSS',
        // 接入点Id，手动选择时传入，自动选择不传
        workerId: '',
        // 接入点选择范围:APP/PUBLIC/ALL，分别为业务私有接入点/公共接入点/全部
        workerSelectScope: 'APP',
        // 接入点选择模式：AUTO/MANUAL，分别为自动/手动
        workerSelectMode: 'AUTO',
    });

    export default {
        name: 'SourceFileOpertion',
        components: {
            RenderFileSourceParam,
        },
        props: {
            data: {
                type: Object,
                default: () => ({}),
            },
        },
        data () {
            return {
                isLoading: false,
                formData: getDefaultData(),
                filePrefixType: FileSourceModel.FILE_PERFIX_UUID,
                // 文件源类型列表
                sourceTypeList: [],
                // 文件源参数
                fileSourceParamList: [],
                // 业务列表
                appList: [],
                // 文件源凭证列表
                fileFourceTicketList: [],
                // 自动选择接入点
                isWorkerSelectScopeAuto: true,
                // 接入点列表
                workersList: [],
            };
        },
        computed: {
            /**
             * @desc 自定义文件前缀名
             * @return {Boolean}
             */
            isCustomFilePrefix () {
                return this.filePrefixType !== FileSourceModel.FILE_PERFIX_UUID;
            },
        },
        watch: {
            /**
             * @desc 共享对象为全业务，清空 sharedAppIdList
             */
            'formData.shareToAllApp' (newVal) {
                if (newVal) {
                    this.formData.sharedAppIdList = [];
                }
            },
            /**
             * @desc 接入点选择范围——获取文件接入点列表
             * 重置接入点为自动选择
             */
            'formData.workerSelectScope' () {
                this.fetchWorkersList();
                this.isWorkerSelectScopeAuto = true;
            },
            /**
             * @desc 自动选择接入点——workerId 为空
             */
            isWorkerSelectScopeAuto (isWorkerSelectScopeAuto) {
                if (isWorkerSelectScopeAuto) {
                    this.formData.workerId = '';
                }
            },
        },
        created () {
            const taskQueue = [
                this.fetchSourceTypeList(),
                this.fetchAppList(),
                this.fetchTicketList(),
                this.fetchWorkersList(),
            ];
            // 编辑文件源
            if (this.data.id) {
                this.formData.id = this.data.id;
                taskQueue.unshift(this.fetchFileSourceDetail());
            }
            this.isLoading = true;
            Promise.all(taskQueue)
                .finally(() => {
                    this.isLoading = false;
                });
            // 接入点选择范围
            this.workerSelectModeList = [
                { id: 'APP', name: I18n.t('file.业务私有') },
                { id: 'PUBLIC', name: I18n.t('file.公共接入点') },
                { id: 'ALL', name: I18n.t('file.全部') },
            ];
            // 表单验证
            this.rules = {
                code: [
                    {
                        required: true,
                        message: I18n.t('file.文件源标识必填'),
                        trigger: 'blur',
                    },
                ],
                alias: [
                    {
                        required: true,
                        message: I18n.t('file.文件源别名必填'),
                        trigger: 'blur',
                    },
                    {
                        validator: fileSourceAliasNameRule.validator,
                        message: fileSourceAliasNameRule.message,
                        trigger: 'blur',
                    },
                    {
                        validator: alias => FileManageService.fetchAliasCheck({
                            fileSourceId: this.formData.id,
                            alias,
                        }),
                        message: I18n.t('file.文件源别名已存在，请重新输入'),
                        trigger: 'blur',
                    },
                ],
                sharedAppIdList: [
                    {
                        validator: (sharedAppIdList) => {
                            if (this.formData.shareToAllApp) {
                                return true;
                            }
                            return sharedAppIdList.length > 0;
                        },
                        message: I18n.t('file.共享对象必填'),
                        trigger: 'blur',
                    },
                ],
                credentialId: [
                    {
                        required: true,
                        message: I18n.t('file.身份凭证必填'),
                        trigger: 'blur',
                    },
                ],
            };
        },
        methods: {
            /**
             * @desc 获取文件源类型列表
             */
            fetchSourceTypeList () {
                return FileSourceType.sourceTypeList()
                    .then((data) => {
                        this.sourceTypeList = Object.freeze(data);
                        if (!this.formData.fileSourceTypeCode && this.sourceTypeList.length > 0) {
                            this.formData.fileSourceTypeCode = this.sourceTypeList[0].code;
                        }
                    });
            },
            /**
             * @desc 获取业务列表数据
             */
            fetchAppList () {
                return AppService.fetchAppList()
                    .then((data) => {
                        this.appList = Object.freeze(data);
                    });
            },
            /**
             * @desc 获取身份凭证列表数据
             */
            fetchTicketList () {
                return TicketService.fetchList()
                    .then((res) => {
                        this.fileFourceTicketList = Object.freeze(res.data);
                    });
            },
            /**
             * @desc 获取接入点列表数据
             */
            fetchWorkersList () {
                return FileWorker.workersList({
                    workerSelectScope: this.formData.workerSelectScope,
                }).then((data) => {
                    this.workersList = Object.freeze(data);
                });
            },
            /**
             * @desc 获取文件源详情
             */
            fetchFileSourceDetail () {
                return FileManageService.getSourceInfo({
                    id: this.formData.id,
                }).then((data) => {
                    const {
                        alias,
                        code,
                        credentialId,
                        fileSourceInfoMap,
                        filePrefix,
                        fileSourceType,
                        publicFlag,
                        storageType,
                        shareToAllApp,
                        sharedAppIdList,
                        workerId,
                        workerSelectMode,
                        workerSelectScope,
                    } = data;

                    this.formData = {
                        ...this.formData,
                        alias,
                        code,
                        credentialId,
                        fileSourceInfoMap,
                        filePrefix,
                        fileSourceTypeCode: fileSourceType.code,
                        publicFlag,
                        storageType,
                        shareToAllApp,
                        sharedAppIdList,
                        workerId,
                        workerSelectMode,
                        workerSelectScope,
                    };
                    // 没有接入点Id——自动选择接入点
                    this.isWorkerSelectScopeAuto = !workerId;
                    // 文件前缀名不等于 FileSourceModel.FILE_PERFIX_UUID 则是自定义文件前缀名
                    this.filePrefixType = filePrefix === FileSourceModel.FILE_PERFIX_UUID ? filePrefix : 'custom';
                });
            },
            /**
             * @desc 文件源改变重置文件源参数
             */
            handleFileSourceChange () {
                this.formData.fileSourceInfoMap = {};
            },
            /**
             * @desc 文件源参数变化
             * @param {Object} params 文件源参数
             */
            handleFileSourceParamsChange (params) {
                this.formData.fileSourceInfoMap = params;
            },
            /**
             * @desc 新建、编辑确认
             *
             * 校验表单通过后,根据文件源ID是否存在判断新建或编辑
             */
            submit () {
                return this.$refs.fileSourceform.validate()
                    .then(() => {
                        const params = Object.assign({}, this.formData);
                        
                        // workerId 不为空手动选择接入点
                        // workerId 为空自动选择接入点
                        params.workerSelectMode = params.workerId ? 'MANUAL' : 'AUTO';
                        
                        // 没有设置自定义文件前缀——使用默认值
                        if (!params.filePrefix) {
                            params.filePrefix = FileSourceModel.FILE_PERFIX_UUID;
                        }

                        if (params.id < 0) {
                            return FileManageService.addSource(params)
                                .then(() => {
                                    this.messageSuccess(I18n.t('file.创建成功'));
                                    this.$emit('on-change');
                                });
                        }
                        return FileManageService.updateSource(params)
                            .then(() => {
                                this.messageSuccess(I18n.t('file.更新成功'));
                                this.$emit('on-change');
                            });
                    });
            },
        },
    };
</script>
<style lang="postcss">
    .file-source-create-form {
        min-height: 50vh;

        .share-object-box {
            display: flex;
            align-items: center;

            .share-app-select {
                flex: 1 1 auto;
                margin-right: 10px;
            }
        }

        .access-point-box {
            display: flex;
            align-items: center;

            .worker-select {
                width: 220px;
                margin-right: 10px;
            }
        }

        .worker-box {
            .bk-form-radio-button {
                width: 220px;
                margin-top: 10px;

                .bk-radio-button-text {
                    width: 100%;
                }
            }

            .worker-item {
                display: flex;
                font-size: 12px;
                justify-content: space-between;

                .latency {
                    color: #3fc06d;
                }
            }
        }
    }
</style>
